home *** CD-ROM | disk | FTP | other *** search
/ Super PC 28 / Super PC 28 (Shareware para Windows 95 y MS-DOS).iso / spc / win / dido3 / source / readcda.c < prev   
Encoding:
C/C++ Source or Header  |  1994-12-09  |  12.5 KB  |  571 lines

  1. /*
  2.  
  3.   GOAL:
  4.     This program is intended to read CD audio data into a disk file.
  5.  
  6.   Author:
  7.     Yeng-Chee Su (yenchee@csie.nctu.edu.tw)
  8.     Department of Computer Science and Information Engineering
  9.     National Chiao Tung University
  10.     &
  11.     Klaas Hemstra (hst@mh.nl)
  12.     Gouda, the Netherlands
  13.  
  14.   Notice:
  15.     Most CD-ROM drive doesn't have the capability to read raw
  16.     data on compact disk, but some drives can work.  These includes
  17.     Panasonic CR-562B/563B and Toshiba XM-3401B.  This program
  18.     is designed on CR-562B and should work well on it.  If it
  19.     can't work for you, find a better driver around.
  20.     Yeng-Chee Su wrote the first attempt, but the program depended on
  21.     the speed of the file-system for clean 'recordings'.
  22.  
  23.     The buffered read + synchronisation is added later by me.
  24.  
  25. */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <conio.h>
  30. #include <dos.h>
  31. #include <dir.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <fcntl.h>
  35. #include <sys/stat.h>
  36. #include <io.h>
  37.  
  38. #define RAW_MODE 1
  39. #define COOKED_MODE 0
  40. #define READ_MODE RAW_MODE
  41. #if READ_MODE == COOKED_MODE
  42.   #define FRAME_SIZE 2048
  43. #else
  44.   #define FRAME_SIZE 2352
  45. #endif
  46. #define NBLOCK 16        // aantal sectoren dat tegelijkertijd met readlong gelezen wordt
  47. #define NBUF   10        // Aantal buffers; elke buffer kan NBLOCK raw sectors bevatten (FRAMESIZE bytes)
  48.                         // een buffer bevat dus 37632 bytes; 10 buffers zijn 376320 bytes.
  49.                         // Plus een 'previous-end' buffer maakt dat 413952 bytes
  50. #define SYNCH_SIZE 128  /* Bytes synch pattern */
  51.  
  52. typedef unsigned char BYTE;
  53. typedef unsigned int WORD;
  54. typedef unsigned long int DWORD;
  55.  
  56. struct ReqHdr {
  57.   BYTE len;
  58.   BYTE unit;
  59.   BYTE command;
  60.   WORD status;
  61.   BYTE reserved[8];
  62. };
  63.  
  64. struct IOCTLI {
  65.   struct ReqHdr req;
  66.   BYTE descriptor;
  67.   void far *address;
  68.   WORD len;
  69.   WORD secnum;
  70.   void far *ptr;
  71. };
  72.  
  73. struct DeviceStatus {
  74.   BYTE control;
  75.   DWORD param;
  76. };
  77.  
  78. struct DiskInfo {
  79.   BYTE control;
  80.   BYTE lowest;
  81.   BYTE highest;
  82.   DWORD total;
  83. };
  84.  
  85. struct TrackInfo {
  86.   BYTE control;
  87.   BYTE track;
  88.   DWORD loc;
  89.   BYTE info;
  90. };
  91.  
  92. struct SEEK {
  93.   struct ReqHdr req;
  94.   BYTE mode;
  95.   DWORD address;
  96.   WORD secnum;
  97.   DWORD loc;
  98. };
  99.  
  100. struct PlayReq {
  101.   struct ReqHdr req;
  102.   BYTE mode;
  103.   DWORD loc;
  104.   DWORD secnum;
  105. };
  106.  
  107. int CDROM;
  108. int lowest, highest;
  109. DWORD total_time;
  110. char image[MAXPATH];
  111.  
  112. void CallDevice(void *ptr)
  113. {
  114.   static union REGS reg;
  115.   static struct SREGS seg;
  116.  
  117.   segread(&seg);
  118.   seg.es=FP_SEG(ptr);
  119.   reg.x.ax=0x1510;
  120.   reg.x.bx=FP_OFF(ptr);
  121.   reg.x.cx=CDROM;
  122.   int86x(0x2f, ®, ®, &seg);
  123. }
  124.  
  125. int check_mscdex(void)
  126. {
  127.   union REGS reg;
  128.  
  129.   reg.x.ax=0x1500;
  130.   reg.x.bx=0;
  131.   int86(0x2f, ®, ®);
  132.   if (!reg.x.bx)
  133.      return 0;
  134.   else {
  135.      CDROM=reg.x.cx;
  136.      return 1;
  137.   }
  138. }
  139.  
  140. int GetDeviceStatus(void)
  141. {
  142.   struct IOCTLI cmd;
  143.   struct DeviceStatus buf;
  144.  
  145.   cmd.req.len=26;
  146.   cmd.req.unit=0;
  147.   cmd.req.command=3;
  148.   cmd.descriptor=0;
  149.   cmd.address=&buf;
  150.   cmd.len=5;
  151.   cmd.secnum=0;
  152.   cmd.ptr=NULL;
  153.   buf.control=6;
  154.   CallDevice(&cmd);
  155.   return cmd.req.status;
  156. }
  157.  
  158. int GetDiskInfo(void)
  159. {
  160.   struct IOCTLI cmd;
  161.   struct DiskInfo buf;
  162.  
  163.   cmd.req.len=26;
  164.   cmd.req.unit=0;
  165.   cmd.req.command=3;
  166.   cmd.descriptor=0;
  167.   cmd.address=&buf;
  168.   cmd.len=7;
  169.   cmd.secnum=0;
  170.   cmd.ptr=NULL;
  171.   buf.control=10;
  172.   CallDevice(&cmd);
  173.   lowest=buf.lowest;
  174.   highest=buf.highest;
  175.   total_time=buf.total;
  176.   return cmd.req.status;
  177. }
  178.  
  179. int GetTrackInfo(int track, DWORD *loc, BYTE *info)
  180. {
  181.   struct IOCTLI cmd;
  182.   struct TrackInfo buf;
  183.  
  184.   cmd.req.len=26;
  185.   cmd.req.unit=0;
  186.   cmd.req.command=3;
  187.   cmd.descriptor=0;
  188.   cmd.address=&buf;
  189.   cmd.len=7;
  190.   cmd.secnum=0;
  191.   cmd.ptr=NULL;
  192.   buf.control=11;
  193.   buf.track=track;
  194.   CallDevice(&cmd);
  195.   *loc=buf.loc;
  196.   *info=buf.info;
  197.   return cmd.req.status;
  198. }
  199.  
  200. int SeekTrack(DWORD loc)
  201. {
  202.   struct SEEK cmd;
  203.  
  204.   cmd.req.len=24;
  205.   cmd.req.unit=0;
  206.   cmd.req.command=131;
  207.   cmd.mode=1;
  208.   cmd.address=NULL;
  209.   cmd.secnum=0;
  210.   cmd.loc=loc;
  211.   CallDevice(&cmd);
  212.   return cmd.req.status;
  213. }
  214.  
  215. int PlayAudio(DWORD loc, DWORD num)
  216. {
  217.   struct PlayReq cmd;
  218.  
  219.   cmd.req.len=22;
  220.   cmd.req.unit=0;
  221.   cmd.req.command=132;
  222.   cmd.mode=1;
  223.   cmd.loc=loc;
  224.   cmd.secnum=num;
  225.   CallDevice(&cmd);
  226.   return cmd.req.status;
  227. }
  228.  
  229. int StopAudio(void)
  230. {
  231.   struct ReqHdr cmd;
  232.  
  233.   cmd.len=13;
  234.   cmd.unit=0;
  235.   cmd.command=133;
  236.   CallDevice(&cmd);
  237.   return cmd.status;
  238. }
  239.  
  240. DWORD Red2Sierra(DWORD loc)
  241. {
  242.   BYTE min, sec, frame;
  243.  
  244.   min = (loc >> 16) & 0xff;
  245.   sec = (loc >> 8) & 0xff;
  246.   frame = loc & 0xff;
  247.   return (DWORD)min * 75 * 60 + (DWORD)sec * 75 + (DWORD)frame - 150;
  248. }
  249.  
  250. int ReadLong(DWORD loc, WORD secnum, char far *buf)
  251. {
  252.   struct ReadL {
  253.     struct ReqHdr req;
  254.     BYTE mode;
  255.     void far *address;
  256.     WORD secnum;
  257.     DWORD loc;
  258.     BYTE readmode;
  259.     BYTE skip[2];
  260.   } cmd;
  261.  
  262.   cmd.req.len=sizeof(cmd);
  263.   cmd.req.unit=0;
  264.   cmd.req.command=128;
  265.   cmd.mode=0;
  266.   cmd.address=buf;
  267.   cmd.secnum=secnum;
  268.   cmd.loc=loc;
  269.   cmd.readmode=READ_MODE;
  270.   cmd.skip[0]=cmd.skip[1]=0;
  271.   CallDevice(&cmd);
  272.   return cmd.req.status;
  273. }
  274.  
  275. int GetVolSize(DWORD *size)
  276. {
  277.   struct IOCTLI cmd;
  278.   struct {
  279.     BYTE control;
  280.     DWORD size;
  281.   } buf;
  282.  
  283.   cmd.req.len=sizeof(cmd);
  284.   cmd.req.unit=0;
  285.   cmd.req.command=3;
  286.   cmd.descriptor=0;
  287.   cmd.address=&buf;
  288.   cmd.len=sizeof(buf);
  289.   cmd.secnum=0;
  290.   cmd.ptr=NULL;
  291.   buf.control=8;
  292.   CallDevice(&cmd);
  293.   *size=buf.size;
  294.   return cmd.req.status;
  295. }
  296.  
  297. char *
  298. location_str( DWORD loc)
  299. {
  300.     static char ret_buf[256];
  301.     long min,sec,frames;
  302.  
  303.     frames = loc % 75;
  304.     sec = (loc+150) / 75;
  305.     min = sec / 60;
  306.     sec = sec % 60;
  307.  
  308.     sprintf(ret_buf,"High sierra %ld ; %02ld:%02ld.%02ld",loc,min,sec,frames);
  309.     return ret_buf;
  310. }
  311.  
  312. void
  313. read_location(char *question,DWORD *loc)
  314. {
  315. #define MAX_LOC 256
  316.     char buf[MAX_LOC],*p;
  317.     buf[0] = '\0';
  318.  
  319.     while (buf[0] == '\0') {
  320.     printf("%s",question);
  321.     fgets(buf,MAX_LOC,stdin);
  322.     }
  323.     for (p=buf;*p && (*p != ':'); p++)
  324.       ;
  325.     if (*p == ':') {
  326.       *loc = atol(buf)*75L*60L+atol(p+1)*75L;
  327.     } else {
  328.       *loc = atol(buf);
  329.     }
  330. }
  331.  
  332.  
  333. void main()
  334. {
  335.   WORD status;
  336.   char *buf[NBUF],*previous_end;
  337.   DWORD *track_loc, loc, end_pos, size;
  338.   DWORD i, j, offset,synch_size;
  339.   BYTE info;
  340.   int fd, key, n,first_time;
  341.   int retry, waveform;
  342.   struct RIFF {
  343.     char rID[4];
  344.     DWORD rLen;
  345.   } riff;
  346.   struct FORMAT {
  347.     char fID[4];
  348.     DWORD fLen;
  349.     WORD wTag;
  350.     WORD wChannel;
  351.     DWORD nSample;
  352.     DWORD nByte;
  353.     WORD align;
  354.     WORD sample;
  355.   };
  356.   struct DATA {
  357.     char dID[4];
  358.     DWORD dLen;
  359.   };
  360.   struct WAVE {
  361.     char wID[4];
  362.     struct FORMAT fmt;
  363.     struct DATA data;
  364.   } wave;
  365.  
  366.   printf("CD-ROM digital audio data extractor, Ver 1.1\n");
  367.   printf(" written by Yeng-Chee Su, CSIE, NCTU & Klaas Hemstra (hst@mh.nl)\n");
  368.   printf("\n");
  369.  
  370.     // Allocate memory buffers
  371.     for (i=0; i< NBUF; i++) buf[i] = (char*)malloc((long)FRAME_SIZE * NBLOCK);
  372.     if (!buf[NBUF-1]) {
  373.         printf("Out of memory!\n");
  374.         exit(1);
  375.         }
  376.     previous_end = (char*)malloc((long)FRAME_SIZE * NBLOCK);
  377.     if (!previous_end) {
  378.         printf("Out of memory!\n");
  379.         exit(1);
  380.         }
  381.  
  382.     // Get Disk info
  383.     if (!check_mscdex()) {
  384.         printf("No CD-ROM extension available!\n");
  385.         exit(1);
  386.         }
  387.  
  388.   retry=0;
  389.   status=GetDiskInfo();
  390.   while (status != 0x0100) {
  391.     printf("Can't get CD-ROM information, status=%x\n", status);
  392.     delay(1000);
  393.     retry++;
  394.     if (retry == 3) {
  395.       printf("Get CD-ROM information failed\n");
  396.       exit(1);
  397.     }
  398.     status=GetDiskInfo();
  399.   }
  400.   track_loc=(DWORD*)malloc(sizeof(DWORD)*(highest-lowest+2));
  401.   if (track_loc==NULL) {
  402.         printf("Out of memory!\n");
  403.         exit(1);
  404.           }
  405.   track_loc = &track_loc[-lowest];
  406.   track_loc[highest+1]=total_time;
  407.   for (i=lowest; i<=highest; i++) {
  408.         status=GetTrackInfo(i, &loc, &info);
  409.         track_loc[i]=loc;
  410.           }
  411.   for (i=lowest; i<=highest; i++)
  412.     printf("Track %2ld : %02ld:%02ld.%02ld %6ld Len = %ld\n", i,
  413.         (track_loc[i] >> 16) & 0xff,
  414.          (track_loc[i] >> 8) & 0xff,
  415.         track_loc[i] & 0xff,
  416.  
  417.         Red2Sierra(track_loc[i]),
  418.          Red2Sierra(track_loc[i+1])-Red2Sierra(track_loc[i]));
  419.  
  420.       printf("Total time : %02ld:%02ld.%02ld\n",
  421.         (total_time >> 16) & 0xff,
  422.            (total_time >> 8) & 0xff,
  423.         total_time & 0xff);
  424.  
  425.     // User interface
  426.   printf("Image filename:");
  427.   gets(image);
  428.   printf("(0) CDDA format, (1) WAV format :");
  429.   key = getch();
  430.   while (key != '0' && key != '1')
  431.     key = getch();
  432.   printf("%c\n", key);
  433.   if (key == '1') waveform = 1; else waveform = 0;
  434.  
  435.   printf("(0) Read Track, (1) Read A to B :");
  436.   key = getch();
  437.   while (key != '0' && key != '1')
  438.     key = getch();
  439.   printf("%c\n", key);
  440.   if (key == '1') {
  441.     read_location("Start location (High sierra or min:sec) : ",&loc);
  442.     read_location("Frame length (Sectors or min:sec) : ",&size);
  443.   } else {
  444. track_again:
  445.     printf("Which track :");
  446.     scanf("%d", &n);
  447.     if (n < lowest || n > highest) {
  448.       printf("illega track!\n");
  449.       goto track_again;
  450.     }
  451.     loc = Red2Sierra(track_loc[n]);
  452.     size = Red2Sierra(track_loc[n+1]) - Red2Sierra(track_loc[n]);
  453.   }
  454.   printf("Start location %s\n", location_str(loc));
  455.   printf("Stop location %s\n", location_str(loc+size));
  456.  
  457.     // Create WAV file
  458.     _fmode = O_BINARY;
  459.     fd = creat(image, S_IREAD|S_IWRITE);
  460.     if (fd == -1) {
  461.         perror("open");
  462.         exit(1);
  463.         }
  464.  
  465.     if (waveform) {
  466.         strcpy(riff.rID, "RIFF");
  467.         riff.rLen = FRAME_SIZE * (DWORD)size + sizeof(struct WAVE);
  468.         strcpy(wave.wID, "WAVE");
  469.         strcpy(wave.fmt.fID, "fmt ");
  470.         wave.fmt.fLen = sizeof(struct FORMAT) - 8;
  471.         wave.fmt.wTag = 1;
  472.         wave.fmt.wChannel = 2;
  473.         wave.fmt.nSample = 44100L;
  474.         wave.fmt.nByte = 44100L * 4;
  475.         wave.fmt.align = 4;
  476.         wave.fmt.sample = 16;
  477.         strcpy(wave.data.dID, "data");
  478.         wave.data.dLen = FRAME_SIZE * (DWORD)size;
  479.         if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
  480.             perror("write");
  481.             exit(1);
  482.             }
  483.         if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
  484.             perror("write");
  485.             exit(1);
  486.             }
  487.         }
  488.  
  489.     // Read the data in blocks, first in memory
  490.        // loc: start position (sierra sector)
  491.     // size: number of sectors to read
  492.     // end_loc: sector number at where to end 
  493.     wave.data.dLen = 0L;
  494.     first_time = 1;
  495.     end_pos = loc+size;
  496.     while (loc<end_pos) {
  497.         for (i=0;i<NBUF;i++) {
  498.             printf("Reading frame %ld to %ld in memory\n",loc,loc+NBLOCK-1);
  499.             status=ReadLong(loc,NBLOCK,buf[i]);
  500.             if (status!=0x0100) {error("CDROM read error, status %x\n", status); return;}
  501.             loc+=NBLOCK;
  502.             }
  503.         if (first_time == 0) { // Except for first recording, synchronize data to previous data
  504.             offset = 0;
  505.             synch_size = SYNCH_SIZE;
  506.             while (offset == 0) {
  507.                 for (i=(NBLOCK/4)*FRAME_SIZE;i<(((WORD)NBLOCK*FRAME_SIZE)-synch_size);i+=4) {
  508.                     if (memcmp(previous_end+(NBLOCK/2)*FRAME_SIZE,buf[0]+i,synch_size) == 0) {
  509.                         if (offset==0)
  510.                             offset=i;
  511.                         else {
  512.                             synch_size *= 2;
  513.                             if (synch_size>4096) {
  514.                                 fprintf(stderr,"Synchronisation failed, synch size to big !!\n");
  515.                                 exit(1);
  516.                                 }
  517.                             break;
  518.                             }
  519.                         }
  520.                     }
  521.                 if (offset==0) {error("Synchronisation failed, no matching block found !!\n"); return;}
  522.                 }
  523.             }
  524.         else
  525.             offset = 0;
  526.  
  527.  
  528.         first_time = 0;
  529.         memcpy(previous_end,buf[NBUF-1],(long)FRAME_SIZE*NBLOCK);
  530.         printf("\rSynchronized write frame %ld to %ld to disk, offset = %ld    ",
  531.                             loc-(NBUF*NBLOCK),loc-(NBLOCK/2),offset-(NBLOCK/2*FRAME_SIZE));
  532.         for (i=0;(i < NBUF-1);i++) {
  533.             if (write(fd, buf[i]+offset, ((long) FRAME_SIZE * NBLOCK)-offset) == -1) {
  534.                 perror("write");
  535.                 exit(1);
  536.                 }
  537.             wave.data.dLen += (((long) FRAME_SIZE * NBLOCK)-offset);
  538.             offset = 0;
  539.             }
  540.  
  541.         // Write only half of last buffer, The next loop, after synchronisation the rest will be written
  542.         if (write(fd, buf[NBUF-1], ((long) FRAME_SIZE * (NBLOCK/2))) == -1) {
  543.             perror("write");
  544.             exit(1);
  545.             }
  546.         wave.data.dLen += ((long) FRAME_SIZE * (NBLOCK/2));
  547.  
  548.         loc -= NBLOCK;
  549.         // sleep(1); (PeekMessage lusje?)
  550.         }
  551.  
  552.     // Fix WAV header
  553.     if (waveform) {
  554.         lseek(fd,0L,SEEK_SET);
  555.         printf("\nCompleting header information of WAV file\n");
  556.         riff.rLen = wave.data.dLen + sizeof(struct WAVE);
  557.         if (write(fd, &riff, sizeof(struct RIFF)) != sizeof(struct RIFF)) {
  558.             perror("write");
  559.             exit(1);
  560.             }
  561.         if (write(fd, &wave, sizeof(struct WAVE)) != sizeof(struct WAVE)) {
  562.             perror("write");
  563.             exit(1);
  564.             }
  565.         }
  566.  
  567.     close(fd);
  568.     free(&track_loc[lowest]);
  569.     free(buf);
  570. }
  571.